# /data/Work/dev_project/ywadmin/tasks/views.py
from rest_framework import viewsets, status, filters
from rest_framework.decorators import action
from rest_framework.response import Response
from django_filters.rest_framework import DjangoFilterBackend
from celery import current_app
from django.utils import timezone
from django.conf import settings
from django.db.models import Q
from django_celery_results.models import TaskResult
from django_celery_beat.models import PeriodicTask
import json

# 直接导入 Celery 应用实例
from ywadmin.celery import app
from tasks.models import TaskDefinition, Tasks
from tasks.serializers import TaskDefinitionSerializer, TaskResultSerializer, TasksSerializer, PeriodicTaskSerializer
from tasks.filter import TaskDefinitionFilter, TaskResultFilter
from system.permissions import has_role_permission, MenuBasePermisson
from utils.CommonUtils import CommonPagination
from utils.TaskUtils import serialize_for_taskresult


class TasksViewSet(viewsets.ModelViewSet):
    """周期任务视图集"""
    queryset = Tasks.objects.all().order_by('-update_time')
    serializer_class = TasksSerializer
    pagination_class = CommonPagination
    permission_classes = [MenuBasePermisson]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_fields = ['enabled', 'task_func']
    search_fields = ['task_func', 'enabled', 'name']
    ordering_fields = ['name', 'update_time']

    def perform_create(self, serializer):
        """在保存对象前设置创建者和更新者"""
        serializer.save(creator=self.request.user, updater=self.request.user)
    
    def perform_update(self, serializer):
        """在保存对象前设置更新者"""
        serializer.save(updater=self.request.user)
    
    def destroy(self, request, *args, **kwargs):
        """重写destroy方法捕获异常"""
        try:
            return super().destroy(request, *args, **kwargs)
        except Exception as e:
            return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
    
    @action(detail=True, methods=['post'])
    def run_now(self, request, pk=None):
        """立即执行任务"""
        task = self.get_object()
        
        # 解析参数
        args = task.task_args if task.task_args else []
        kwargs = task.task_kwargs.copy() if task.task_kwargs else {}
        
        # 添加追踪参数到 kwargs(用于任务结果关联)
        # 注意: 所有Celery任务函数都应接受 **kwargs 以支持这些追踪参数
        kwargs['tasks_instance_id'] = task.id
        kwargs['periodic_task_name'] = task.name
        
        # 发送任务到Celery
        celery_task = current_app.send_task(
            task.task_func,
            args=args,
            kwargs=kwargs
        )
        
        return Response({
            'message': '任务已提交执行',
            'task_id': celery_task.id
        })
    
    @action(detail=True, methods=['post'])
    def enable(self, request, pk=None):
        """启用任务"""
        task = self.get_object()
        task.enabled = True
        task.save()
        return Response({'message': '任务已启用'})
    
    @action(detail=True, methods=['post'])
    def disable(self, request, pk=None):
        """禁用任务"""
        task = self.get_object()
        task.enabled = False
        task.save()
        return Response({'message': '任务已禁用'})
    
    @action(detail=False, methods=['get'])
    def available_tasks(self, request):
        """获取可用的任务函数列表"""
        
        # 强制重新发现任务, 重新加载任务,Django 服务器和 Celery worker 是不同的进程，它们各自加载和注册任务
        app.autodiscover_tasks(lambda: settings.INSTALLED_APPS, force=True)
        
        # 获取所有已注册的任务
        registered_tasks = app.tasks

        # 获取已经使用的任务
        used_tasks = set(PeriodicTask.objects.values_list('task', flat=True))

        # 过滤掉Celery内部任务（通常以celery.开头）
        available_tasks = []
        for task_name, task in registered_tasks.items():
            # 排除Celery内部任务
            if not task_name.startswith('celery.'):
                # 获取任务的文档字符串作为描述
                description = task.__doc__ or '无描述'
                # 获取任务的显示名称
                display_name = task_name.split('.')[-1].replace('_', ' ').title()
                
                # 检查任务是否已被使用
                is_used = task_name in used_tasks
                
                available_tasks.append({
                    'name': task_name,
                    'display_name': display_name,
                    'description': description,
                    'is_used': is_used
                })
        
        return Response(available_tasks)


class TaskDefinitionViewSet(viewsets.ModelViewSet):
    """任务定义视图集"""
    queryset = TaskDefinition.objects.all().order_by('-update_time')
    serializer_class = TaskDefinitionSerializer
    # permission_classes = [has_role_permission(['admin']), MenuBasePermisson]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    pagination_class = CommonPagination
    filterset_class = TaskDefinitionFilter
    permission_classes = [MenuBasePermisson]
    filterset_fields = ['task_type', 'name']
    search_fields = ['name', 'description']
    ordering_fields = ['id', 'create_time', 'update_time']
    
    def create(self, request, *args, **kwargs):
        """重写create方法捕获异常"""
        try:
            return super().create(request, *args, **kwargs)
        except ValueError as e:
            return Response({"error": str(e)}, status=400)
        except Exception as e:
            return Response({"error": str(e)}, status=500)
    
    def update(self, request, *args, **kwargs):
        """重写update方法捕获异常"""
        try:
            return super().update(request, *args, **kwargs)
        except ValueError as e:
            return Response({"error": str(e)}, status=400)
        except Exception as e:
            return Response({"error": str(e)}, status=500)
            
    def destroy(self, request, *args, **kwargs):
        """重写destroy方法捕获异常"""
        try:
            # 模型的delete方法已经处理了调度表的删除，直接调用父类方法
            return super().destroy(request, *args, **kwargs)
        except Exception as e:
            return Response({"error": str(e)}, status=400)
    
    def perform_create(self, serializer):
        """创建时自动设置创建者和更新者"""
        serializer.save(creator=self.request.user, updater=self.request.user)
    
    def perform_update(self, serializer):
        """更新时自动设置更新者"""
        serializer.save(updater=self.request.user)


class TaskResultViewSet(viewsets.ModelViewSet):
    """任务结果视图集"""
    queryset = TaskResult.objects.all().order_by('-date_done')
    serializer_class = TaskResultSerializer
    permission_classes = [MenuBasePermisson]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_class = TaskResultFilter
    search_fields = ['task_id', 'task_name', 'periodic_task_name']
    ordering_fields = ['date_done', 'date_created']
    pagination_class = CommonPagination

    def get_queryset(self):
        """自定义查询集，返回所有任务结果"""
        return super().get_queryset()

    @action(detail=False, methods=['get'])
    def last_success_task_results(self, request):
        periodic_task_name = request.query_params.get('periodic_task_name')
        if not periodic_task_name:
            return Response({}, status=200)
        queryset = TaskResult.objects.filter(status='SUCCESS', 
                                            periodic_task_name=periodic_task_name).order_by('-date_done').first()
        if queryset is not None:
            serializer = TaskResultSerializer(queryset)
            return Response(serializer.data)
        else:
            return Response({}, status=200)

    @action(detail=False, methods=['get'])
    def task_stats(self, request):
        """获取任务结果统计信息"""
        # 基本统计
        total_count = TaskResult.objects.count()
        pending_count = TaskResult.objects.filter(status='PENDING').count()
        running_count = TaskResult.objects.filter(status='STARTED').count()
        success_count = TaskResult.objects.filter(status='SUCCESS').count()
        failure_count = TaskResult.objects.filter(status='FAILURE').count()
        revoked_count = TaskResult.objects.filter(status='REVOKED').count()
        retry_count = TaskResult.objects.filter(status='RETRY').count()
        
        # 按任务类型统计
        task_type_stats = {}
        task_names = TaskResult.objects.values_list('task_name', flat=True).distinct()
        for task_name in task_names:
            task_count = TaskResult.objects.filter(task_name=task_name).count()
            success_rate = 0
            if task_count > 0:
                success_rate = TaskResult.objects.filter(task_name=task_name, status='SUCCESS').count() / task_count * 100
            
            task_type_stats[task_name] = {
                'count': task_count,
                'success_rate': round(success_rate, 2)
            }
        
        # 按周期计算成功率
        today = timezone.now().date()
        last_week = today - timezone.timedelta(days=7)
        last_month = today - timezone.timedelta(days=30)
        
        today_success_rate = 0
        today_count = TaskResult.objects.filter(date_done__date=today).count()
        if today_count > 0:
            today_success_rate = TaskResult.objects.filter(date_done__date=today, status='SUCCESS').count() / today_count * 100
        
        week_success_rate = 0
        week_count = TaskResult.objects.filter(date_done__date__gte=last_week).count()
        if week_count > 0:
            week_success_rate = TaskResult.objects.filter(date_done__date__gte=last_week, status='SUCCESS').count() / week_count * 100
        
        month_success_rate = 0
        month_count = TaskResult.objects.filter(date_done__date__gte=last_month).count()
        if month_count > 0:
            month_success_rate = TaskResult.objects.filter(date_done__date__gte=last_month, status='SUCCESS').count() / month_count * 100
        
        return Response({
            'total': total_count,
            'status_counts': {
                'pending': pending_count,
                'running': running_count,
                'success': success_count,
                'failure': failure_count,
                'revoked': revoked_count,
                'retry': retry_count
            },
            'task_type_stats': task_type_stats,
            'time_stats': {
                'today': {
                    'count': today_count,
                    'success_rate': round(today_success_rate, 2)
                },
                'week': {
                    'count': week_count,
                    'success_rate': round(week_success_rate, 2)
                },
                'month': {
                    'count': month_count,
                    'success_rate': round(month_success_rate, 2)
                }
            }
        })
        
    @action(detail=False, methods=['post'])
    def clear_old_results(self, request):
        """清理旧的任务结果"""
        days = request.data.get('days', 30)
        try:
            days = int(days)
            if days < 0:
                return Response({"error": "天数必须大于等于0"}, status=status.HTTP_400_BAD_REQUEST)
                
            cutoff_date = timezone.now() - timezone.timedelta(days=days)
            deleted_count, _ = TaskResult.objects.filter(date_done__lt=cutoff_date).delete()
            
            return Response({
                'message': f'成功清理{deleted_count}条过期任务结果',
                'deleted_count': deleted_count
            })
        except ValueError:
            return Response({"error": "天数必须是有效的整数"}, status=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class PeriodicTaskViewSet(viewsets.ModelViewSet):
    """celery内部周期任务视图集"""
    queryset = PeriodicTask.objects.all().order_by('-start_time')
    serializer_class = PeriodicTaskSerializer
    permission_classes = [MenuBasePermisson]
    pagination_class = CommonPagination
    # permission_classes = [has_role_permission(['admin']), MenuBasePermisson]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_fields = ['name', 'task']
    search_fields = ['task', 'enabled', 'name']
    ordering_fields = ['name', 'start_time']